package cn.chiship.framework.upms.biz.user.service.impl;

import cn.chiship.framework.common.constants.CommonCacheConstants;
import cn.chiship.framework.upms.biz.user.pojo.vo.UpmsUserOnlineVo;
import cn.chiship.framework.upms.biz.user.service.UpmsUserOnlineService;
import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.sdk.cache.service.UserCacheService;
import cn.chiship.sdk.cache.vo.CacheOrganizationVo;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.CacheConstants;
import cn.chiship.sdk.core.useragent.UserAgentUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.core.util.ip.AddressUtils;
import cn.chiship.sdk.framework.pojo.vo.PageVo;
import cn.chiship.sdk.framework.util.ServletUtil;
import org.springframework.stereotype.Service;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author lijian
 */
@Service
public class UpmsUserOnlineServiceImpl implements UpmsUserOnlineService {
    @Resource
    RedisService redisService;
    @Resource
    UserCacheService userCacheService;


    @Override
    public BaseResult page(Long page, Long limit, String ip, String userName) {
        Set<String> keys = redisService.keys(CommonCacheConstants.buildKey(CacheConstants.REDIS_ONLINE_USER_PREFIX) + ":*");
        Iterator<String> iterator = keys.iterator();
        List<UpmsUserOnlineVo> userOnlineVos = new ArrayList<>();
        while (iterator.hasNext()) {
            userOnlineVos.add((UpmsUserOnlineVo) redisService.get(iterator.next()));
        }
        userOnlineVos.sort(new Comparator<UpmsUserOnlineVo>() {
            @Override
            public int compare(UpmsUserOnlineVo o1, UpmsUserOnlineVo o2) {
                if (o1.getLoginTime() > o2.getLoginTime()) {
                    return -1;
                } else if (o1.getLoginTime() < o2.getLoginTime()) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });
        PageVo pageVo = new PageVo();
        pageVo.setCurrent(page);
        pageVo.setSize(limit);
        pageVo.setTotal(Long.valueOf(userOnlineVos.size()));
        pageVo.setRecords(userOnlineVos);
        return BaseResult.ok(pageVo);
    }

    @Override
    public BaseResult loginUserToUserOnline(String token, @ApiIgnore CacheUserVO userVO, String ip) {
        UserAgentUtil userAgent = UserAgentUtil.parseUserAgentString(ServletUtil.getRequest().getHeader("User-Agent"));
        UpmsUserOnlineVo userOnlineVo = new UpmsUserOnlineVo();
        userOnlineVo.setSessionId(userVO.getSessionId());
        userOnlineVo.setToken(token);
        userOnlineVo.setUserName(userVO.getUsername());
        CacheOrganizationVo organizationVo = userVO.getCacheOrganizationVo();
        if (!StringUtil.isNull(organizationVo)) {
            userOnlineVo.setOrgName(organizationVo.getOrganizationName());
        }
        userOnlineVo.setIp(ip);
        if (!StringUtil.isNull(userAgent.getBrowserVersion())) {
            userOnlineVo.setBrowser(userAgent.getBrowser().getName() + "(" + userAgent.getBrowserVersion().getVersion() + ")");
        } else {
            userOnlineVo.setBrowser(userAgent.getBrowser().getName());
        }
        userOnlineVo.setOs(userAgent.getOperatingSystem().getName());
        userOnlineVo.setLoginTime(System.currentTimeMillis());
        userOnlineVo.setLoginAddress(AddressUtils.getRealAddressByIp(ip));
        redisService.set(CommonCacheConstants.buildKey(CacheConstants.REDIS_ONLINE_USER_PREFIX) + ":" + userOnlineVo.getSessionId(), userOnlineVo);
        return BaseResult.ok();
    }

    @Override
    public BaseResult forceLogout(String sessionId) {
        String key = CommonCacheConstants.buildKey(CacheConstants.REDIS_ONLINE_USER_PREFIX) + ":" + sessionId;
        UpmsUserOnlineVo userOnlineVo = (UpmsUserOnlineVo) redisService.get(key);
        redisService.del(key);
        if (!StringUtil.isNull(userOnlineVo)) {
            userCacheService.removeUserByToken(userOnlineVo.getToken());
        }
        return BaseResult.ok();
    }
}
